package oldmodifiers;

import inputs.Input;

import java.util.List;
import java.util.Random;

public enum Modifiers {
	Sum{
		public ModifierData Update(List<Input> inputs, ModifierData prevData)
		{
			SumData sumData;
			if (prevData == null)
			{
				sumData = new SumData(0);
				sumData = (SumData)AccountForInputs(inputs, sumData);
			}
			else if (prevData instanceof SumData)
				sumData = (SumData)prevData;
			else
			{
				sumData = new SumData(0, prevData.getRun());
				sumData = (SumData)AccountForInputs(inputs, sumData);
			}

			if(!sumData.getRun())
			{
				sumData.value = 0;
				sumData.runCount = 1;
			}
			else
				sumData.runCount++;
			for (Input input : inputs)
			{
				sumData.value += input.getValue();
			}


			return sumData;
		}

		public ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData)
		{
			if(modifierData == null)
				modifierData = new SumData(0);

			modifierData.min = 0;
			modifierData.max = 0;
			for (Input input : inputs)
			{
				modifierData.min += input.getMin();
				modifierData.max += input.getMax();
			}

			return modifierData;
		}
	},

	Average{
		public ModifierData Update(List<Input> inputs, ModifierData prevData)
		{
			AverageData avgData;
			if(prevData == null)
			{
				avgData = new AverageData(0);
				avgData = (AverageData)AccountForInputs(inputs, avgData);
			}
			else if (prevData instanceof AverageData)
				avgData = (AverageData)prevData;
			else
			{
				avgData = new AverageData(0, prevData.getRun());
				avgData = (AverageData)AccountForInputs(inputs, avgData);
			}

			if (!avgData.getRun())
			{
				avgData.total = 0;
				avgData.count = 0;
				avgData.runCount = 1;
			}
			else
			{
				avgData.runCount++;
			}
			for (Input input : inputs)
			{
				avgData.total += input.getValue();
				avgData.count++;
			}

			avgData.value = avgData.total / avgData.count;

			return avgData;
		}

		public ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData)
		{
			if (modifierData == null)
				modifierData = new AverageData(0);

			int minTotal = 0;
			int maxTotal = 0;
			int count = 0;


			for(Input input : inputs)
			{
				minTotal += input.getMin();
				maxTotal += input.getMax();
				count++;
			}

			modifierData.min = minTotal / count;
			modifierData.max = maxTotal / count;

			return modifierData;
		}
	},

	HighPass{
		public ModifierData Update(List<Input> inputs, ModifierData prevData)
		{

			if(!(prevData instanceof ModifierData))
			{
				prevData = new ModifierData(0);
				prevData = AccountForInputs(inputs, prevData);
			}

			prevData.value = -1;

			if (inputs.size() > 1)
			{
				if (inputs.get(0).getValue() < inputs.get(1).getValue())
					prevData.value = inputs.get(1).getValue();
			}

			return prevData;
		}

		public ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData)
		{
			if (modifierData == null)
				modifierData = new ModifierData(0);

			if (inputs.size() < 2)
			{
				modifierData.min = 0;
				modifierData.max = 0;
			}
			else
			{
				Input input = inputs.get(1);
				modifierData.min = input.getMin();
				modifierData.max = input.getMax();
			}

			return modifierData;
		}
	},

	LowPass{
		public ModifierData Update(List<Input> inputs, ModifierData prevData)
		{

			if(!(prevData instanceof ModifierData))
			{
				prevData = new ModifierData(0);
				prevData = AccountForInputs(inputs, prevData);
			}

			prevData.value = -1;

			if (inputs.size() > 1)
			{
				if (inputs.get(0).getValue() > inputs.get(1).getValue())
					prevData.value = inputs.get(1).getValue();
			}

			return prevData;
		}

		public ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData)
		{
			if (modifierData == null)
				modifierData = new ModifierData(0);

			if (inputs.size() < 2)
			{
				modifierData.min = 0;
				modifierData.max = 0;
			}
			else
			{
				Input input = inputs.get(1);
				modifierData.min = input.getMin();
				modifierData.max = input.getMax();
			}

			return modifierData;
		}
	},

	Random{
		public ModifierData Update(List<Input> inputs, ModifierData prevData)
		{
			if (!(prevData instanceof ModifierData))
			{
				prevData = new ModifierData(0);
				prevData = AccountForInputs(inputs, prevData);
			}		
			
			prevData.setValue(inputs.get(rn.nextInt(inputs.size())).getValue());
			return prevData;
		}
		
		public ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData)
		{
			if (!(modifierData instanceof ModifierData))
				modifierData = new ModifierData(0);
			
			if (inputs.size() > 0)
			{
				modifierData.min = inputs.get(0).getMin();
				modifierData.max = inputs.get(0).getMax();
				
				for (Input input : inputs)
				{
					if (input.getMin() < modifierData.min)
						modifierData.min = input.getMin();
					
					if (input.getMax() > modifierData.max)
						modifierData.max = input.getMax();
				}
			}
			else
			{
				modifierData.min = 0;
				modifierData.max = 0;
			}
			
			return modifierData;
		}
	}
	;

	public ModifierData Update(List<Input> inputs)
	{
		return Update(inputs, null);
	}

	static Random rn = new Random();

	public abstract ModifierData Update(List<Input> inputs, ModifierData prevData);
	public abstract ModifierData AccountForInputs(List<Input> inputs, ModifierData modifierData);

}
